#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <pthread.h>
#include "../include/log.h"

static unsigned char g_ucLogFileName[MAX_LOG_FILE_NUM][STR_COMM_SIZE] = {{0}};
static unsigned char g_ucLogFileNo = 0;

unsigned long g_ulPrintLogPlaceFlag = 0;

static unsigned long g_ulLogFileSize = 0;

static FILE *pFile = NULL;

static pthread_mutex_t g_stSaveLogMutexLock;

static unsigned long g_ulLogInitFlag = 0;

void LOG_SetPrintLogPlaceFlag(unsigned long flag)
{
    g_ulPrintLogPlaceFlag = flag;
}



static long get_file_size(const char *path)
{
    long filesize = -1;
    struct stat statbuff;

    if (stat(path, &statbuff) < 0)
    {
        return filesize;
    }
    else
    {
        filesize = statbuff.st_size;
    }
    return filesize;
}

unsigned long LOG_PrintLogTime(unsigned char *ucTime, unsigned long ulBufLen)
{
    struct tm *pstTmSec;
    struct timeval stTmMsec;

    if (NULL == ucTime)
    {
        return -1;
    }
    gettimeofday(&stTmMsec, NULL);
    pstTmSec = localtime(&stTmMsec.tv_sec);
    snprintf((char *)ucTime, ulBufLen - 1, "%04d-%02d-%02d %02d:%02d:%02d %s",
             pstTmSec->tm_year + 1900, pstTmSec->tm_mon + 1, pstTmSec->tm_mday, pstTmSec->tm_hour,
             pstTmSec->tm_min, pstTmSec->tm_sec, pstTmSec->tm_zone);

    return 0;
}

unsigned long LOG_LogTypeToStr(unsigned char ucType, unsigned char *pucTypeString, unsigned long ulBufLen)
{
    if (NULL == pucTypeString)
    {
        return -1;
    }
    //防止发生越界
    ulBufLen -= 1;

    switch (ucType)
    {
    case LOG_DEBUG:
    {
        strncpy((char *)pucTypeString, "DEBUG", ulBufLen);
        break;
    }
    case LOG_ERROR:
    {
        strncpy((char *)pucTypeString, "ERROR", ulBufLen);
        break;
    }
    case LOG_WARNING:
    {
        strncpy((char *)pucTypeString, "WARNING", ulBufLen);
        break;
    }
    case LOG_ACTION:
    {
        strncpy((char *)pucTypeString, "ACCESS", ulBufLen);
        break;
    }
    case LOG_SYSTEM:
    {
        strncpy((char *)pucTypeString, "SYSTEM", ulBufLen);
        break;
    }
    default:
    {
        strncpy((char *)pucTypeString, "UNKNOWN", ulBufLen);
        break;
    }
    }
    return 0;
}

unsigned long LOG_OpenLogFile(void)
{
    char *path = (char *)g_ucLogFileName[g_ucLogFileNo];
    char *flag = NULL;
    int len = 0;

    if (NULL != pFile)
        return 0;
    if (NULL == path)
    {
        LOG_ERR("%s", "file name is NULL.");
        return -1;
    }

    if (!access(path, 0))
    {
        if (0 > (len = get_file_size(path)))
        {
            LOG_ERR("%s", "get file size failed!");
            return -1;
        }
    }
    flag = (len > 0 && len < g_ulLogFileSize) ? "a" : "w";

    pFile = fopen(path, flag);
    if (NULL == pFile)
    {
        LOG_ERR("%s", "open file failed!");
        return -1;
    }
    return 0;
}

unsigned long LOG_PrintLog(unsigned char ucType, unsigned char *pucLogInfo)
{
    unsigned long ulResult = 0;
    unsigned long ulFileLen = 0;
    unsigned char ucTime[STR_COMM_SIZE] = {0};
    unsigned char ucLogTypeStr[STR_COMM_SIZE] = {0};
    unsigned char ucLogInfo[STR_MAX_SIZE] = {0};

    if (NULL == pucLogInfo)
    {
        return -1;
    }

    ulResult = LOG_LogTypeToStr(ucType, ucLogTypeStr, sizeof(ucLogTypeStr));
    ulResult += LOG_PrintLogTime(ucTime, sizeof(ucTime));
    if (0 != ulResult)
    {
        return -1;
    }
    snprintf((char *)ucLogInfo, sizeof(ucLogInfo) - 1, "[%s] [%s] %s", ucTime, ucLogTypeStr, pucLogInfo);
    if (PRINT_LOG_TO_TERM == g_ulPrintLogPlaceFlag)
    {
        printf("%s", ucLogInfo);
        return 0;
    }
    //加锁
    pthread_mutex_lock(&g_stSaveLogMutexLock);
    (void)LOG_OpenLogFile();
    if (NULL != pFile)
    {
        fputs((char *)ucLogInfo, pFile);
        ulFileLen = ftell(pFile);
        if (ulFileLen >= g_ulLogFileSize)
        {
            fclose(pFile);
            pFile = NULL;
            g_ucLogFileNo = (g_ucLogFileNo + 1) % MAX_LOG_FILE_NUM;
        }
    }
    pthread_mutex_unlock(&g_stSaveLogMutexLock);
    return 0;
}

unsigned long LOG_Init( unsigned char *ucLogFileName, unsigned long ulFileSize)
{
    unsigned int i = 0;
    if ((NULL == ucLogFileName) || !(ulFileSize > 0))
    {
        LOG_ERR("%s", "open file failed!");
        return -1;
    }
    if ((PRINT_LOG_TO_FILE != g_ulPrintLogPlaceFlag) || (0 != g_ulLogInitFlag))
    {
        printf("g_ulPrintLogPlaceFlag = %ld g_ulLogInitFlag = %ld\n", g_ulPrintLogPlaceFlag, g_ulLogInitFlag);
        return 0;
    }

    g_ulLogInitFlag = 1;

    for (i = 0; i < NUMBER(g_ucLogFileName); i++)
    {
        snprintf((char *)g_ucLogFileName[i], sizeof(g_ucLogFileName[i]) - 1, "./LOG/%s_%2d.log", ucLogFileName, i);
        // printf("Log File: %s\n", g_ucLogFileName[i]);
    }
    g_ulLogFileSize = ulFileSize;
    pthread_mutex_init(&g_stSaveLogMutexLock, NULL);

    return 0;
}

void LOG_Destroy(void)
{
    if (pFile != NULL)
    {
        fclose(pFile);
        pFile = NULL;
    }
    pthread_mutex_destroy(&g_stSaveLogMutexLock);
    return;
}
